import java.util.ArrayList;
import java.util.Map;

public class Request {
	public static int portfolioId = 0;
	public static int accountId = 0;
	public static int orderId = 0;
	public static int stockId = 0;
	public static int mutualFundId = 0;

	private portType portfolioType;
	private int requestPortfolioId;
	private int requestAccountId;
	private int requestOrderId;
	private int requestStockId;
	private int requestMutualFundId;
	private int requestStockQuantity;
	private int requestMFQuantity;
	private double requestNewPriceLimit;
	private int requestNewQuantity;
	private int requestId;
	private int accountRequest;
	private int orderRequest;
	private double stockPrice;
	private double mutualFundPrice;
	private SecurityType securityType;
	private OrderType orderType;
	private OrderCategory orderCategory;
	private double priceLimit;
	private double accountBalance;
	private int timeStamp;
	private int mutualFundUnits;
	private NotificationFormat notificationformat;

	public int getMutualFundUnits() {
		return mutualFundUnits;
	}

	public void setMutualFundUnits(int mutualFundUnits) {
		this.mutualFundUnits = mutualFundUnits;
	}

	public double getRequestNewPriceLimit() {
		return requestNewPriceLimit;
	}

	public void setRequestNewPriceLimit(double requestNewPriceLimit) {
		this.requestNewPriceLimit = requestNewPriceLimit;
	}

	public int getRequestOrderId() {
		return requestOrderId;
	}

	public void setRequestOrderId(int requestOrderId) {
		this.requestOrderId = requestOrderId;
	}

	public int getRequestMFQuantity() {
		return requestMFQuantity;
	}

	public void setRequestMFQuantity(int requestMFQuantity) {
		this.requestMFQuantity = requestMFQuantity;
	}

	public int getRequestMutualFundId() {
		return requestMutualFundId;
	}

	public void setRequestMutualFundId(int requestMutualFundId) {
		this.requestMutualFundId = requestMutualFundId;
	}

	public int getRequestNewQuantity() {
		return requestNewQuantity;
	}

	public void setRequestNewQuantity(int requestNewQuantity) {
		this.requestNewQuantity = requestNewQuantity;
	}

	public int getRequestStockId() {
		return requestStockId;
	}

	public void setRequestStockId(int requestStockId) {
		this.requestStockId = requestStockId;
	}

	public int getRequestStockQuantity() {
		return requestStockQuantity;
	}

	public void setRequestStockQuantity(int requestStockQuantity) {
		this.requestStockQuantity = requestStockQuantity;
	}

	public double getAccountBalance() {
		return accountBalance;
	}

	public void setAccountBalance(double accountBalance) {
		this.accountBalance = accountBalance;
	}

	public double getPriceLimit() {
		return priceLimit;
	}

	public void setPriceLimit(double priceLimit) {
		this.priceLimit = priceLimit;
	}

	public int getTimeStamp() {
		return timeStamp;
	}

	public void setTimeStamp(int timeStamp) {
		this.timeStamp = timeStamp;
	}

	public OrderType getOrderType() {
		return orderType;
	}

	public void setOrderType(OrderType orderType) {
		this.orderType = orderType;
	}

	public OrderCategory getOrderCategory() {
		return orderCategory;
	}

	public void setOrderCategory(OrderCategory orderCategory) {
		this.orderCategory = orderCategory;
	}

	public SecurityType getSecurityType() {
		return securityType;
	}

	public void setSecurityType(SecurityType securityType) {
		this.securityType = securityType;
	}

	public int getRequestAccountId() {
		return requestAccountId;
	}

	public void setRequestAccountId(int requestAccountId) {
		this.requestAccountId = requestAccountId;
	}

	public double getMutualFundPrice() {
		return mutualFundPrice;
	}

	public void setMutualFundPrice(double mutualFundPrice) {
		this.mutualFundPrice = mutualFundPrice;
	}

	public double getStockPrice() {
		return stockPrice;
	}

	public void setStockPrice(double stockPrice) {
		this.stockPrice = stockPrice;
	}

	private Map<Integer, Integer> stockDetailsInMf;

	public Map<Integer, Integer> getStockDetailsInMf() {
		return stockDetailsInMf;
	}

	public void setStockDetailsInMf(Map<Integer, Integer> stockDetailsInMf) {
		this.stockDetailsInMf = stockDetailsInMf;
	}

	public int getOrderRequest() {
		return orderRequest;
	}

	public void setOrderRequest(int orderRequest) {
		this.orderRequest = orderRequest;
	}

	public int getAccountRequest() {
		return accountRequest;
	}

	public void setAccountRequest(int accountRequest) {
		this.accountRequest = accountRequest;
	}

	public int getRequestId() {
		return requestId;
	}

	public void setRequestId(int requestId) {
		this.requestId = requestId;
	}

	public portType getPortfolioType() {
		return portfolioType;
	}

	public void setPortfolioType(portType portfolioType) {
		this.portfolioType = portfolioType;
	}

	public int getRequestPortfolioId() {
		return requestPortfolioId;
	}

	public void setRequestPortfolioId(int requestPortfolioId) {
		this.requestPortfolioId = requestPortfolioId;
	}

	public void listSecurity(int formatchoice) {
		switch (formatchoice) {
		case 1:
			notificationformat = new OnlineFormat();
			break;
		case 2:
			notificationformat = new EmailFormat();
			break;
		}

		Report report = new DisplayStock(notificationformat);

		report.format.display();
		report.listAll();

		report = new DisplayMutualFund(notificationformat);
		report.format.display();
		report.listAll();
	}

	public void listOrders(int format) {
		switch (format) {
		case 1:
			notificationformat = new OnlineFormat();
			break;
		case 2:
			notificationformat = new EmailFormat();
			break;
		}
		OrderRepository orderRepository = OrderRepository.getOrderRepository();
		orderRepository.displayAllOrders();
	}

	public void processRequest() {
		switch (requestId) {
		case Constants.CREATE_PORTFOLIO: {
			portfolioId++;
			Portfolio portfolio = new Portfolio(portfolioId, portfolioType,
					acctype.CASH);
			PortfolioRepository.getPortfolioRepository()
					.addPortfolio(portfolio);
			Account account = new Account();
			accountId++;
			account.createAccount(accountId, acctype.CASH, portfolioId);
			portfolio.getAccounts().add(account);
			portfolio.display();
			break;
		}
		case Constants.MANAGE_ACCOUNTS: {
			Portfolio portfolio = PortfolioRepository.getPortfolioRepository()
					.getPortfolioWithID(requestPortfolioId);
			portfolio.setPortfolioId(requestPortfolioId);
			switch (accountRequest) {
			case 1: {
				accountId++;
				Account account = new Account();
				account.createAccount(accountId, acctype.SAVING,
						requestPortfolioId);
				account.displayAccountDetails();
				portfolio.getAccounts().add(account);
				break;
			}
			case 2: {
				for (Account account : portfolio.getAccounts()) {
					account.displayAccountDetails();
				}
				break;
			}
			case 3: {
				Account account = PortfolioRepository.getPortfolioRepository()
						.getAccount(requestAccountId);
				account.setBalance(accountBalance);
				account.displayAccountDetails();
				break;
			}
			case 4:
				break;
			}
			break;
		}
		case Constants.MANAGE_ORDERS: {
			Portfolio portfolio = PortfolioRepository.getPortfolioRepository()
					.getPortfolioWithID(requestPortfolioId);
			if ((portType.COMPANY).equals(portfolioType)) {
				switch (orderRequest) {
				case 1: {
					stockId++;
					Stock stock = new Stock();
					stock.setPortfolioId(requestPortfolioId);
					stock.setAccountId(requestAccountId);
					stock.addSecurity(stockId, stockPrice);
					stock.listSecurity();
					break;
				}

				case 2: {
					System.out.println("\nListing All Stocks: ");
					ArrayList<Stock> stocks = StockRepository
							.getStockRepository().getAllStocks(
									requestPortfolioId);
					Stock.listStocks(stocks);

					System.out.println("\nListing All MutualFunds: ");
					ArrayList<MutualFund> mutualfunds = MutualFundRepository
							.getMutualFundRepository().getAllMutualFunds(
									requestPortfolioId);
					MutualFund.listMutualFunds(mutualfunds);
					break;
				}

				case 3: {
					mutualFundId++;
					MutualFund mutualFund = new MutualFund();
					mutualFund.setPortfolioId(requestPortfolioId);
					mutualFund.setAccountId(requestAccountId);
					mutualFund.setStockDetailsInMf(stockDetailsInMf);
					mutualFund.addSecurity(mutualFundId);
					mutualFund.setMutualFundUnits(mutualFundUnits);
					mutualFund.listSecurity();

					for (Map.Entry<Stock, Integer> stockDetail : MutualFund
							.getStockDetails().entrySet()) {
						Stock stock = stockDetail.getKey();
						int quantity = stockDetail.getValue();
						System.out.println("\nPlacing Order for "
								+ stock.getStockId());
						StockOrder stockOrder = new StockOrder();
						stockOrder.setStockId(stock.getStockId());
						stockOrder.setQuantity(quantity * mutualFundUnits);
						MarketOrder marketOrder = new MarketOrder(stockOrder);
						orderId++;
						marketOrder.createOrder(orderId, OrderCategory.BUY,
								requestAccountId, requestPortfolioId);
						marketOrder.display();
						marketOrder.initializeOrder();
					}

					break;
				}
				}
			} else {
				portfolio.setPortfolioId(requestPortfolioId);
				switch (orderRequest) {
				case 1: {
					AbstractOrder order;
					if ((SecurityType.STOCKS).equals(securityType)) {
						order = new StockOrder();
						order.setSecurityType(SecurityType.STOCKS);
					} else {
						order = new MutualFundOrder();
						order.setSecurityType(SecurityType.MUTUAL_FUNDS);
					}
					order.setOrderCategory(orderCategory);

					if ((SecurityType.STOCKS).equals(securityType)) {
						if ((OrderCategory.BUY).equals(orderCategory)) {
							boolean hasSufficientBalance = order
									.hasSufficientBalance(requestAccountId,
											priceLimit, requestStockQuantity);
							if (!hasSufficientBalance) {
								System.out
										.println("Account does not have sufficient Balance!");
								break;
							}
						}
						order.setStockId(requestStockId);
						order.setQuantity(requestStockQuantity);
						if ((OrderType.LIMIT).equals(orderType)) {
							LimitOrder limitOrder = new LimitOrder(order);

							orderId++;
							limitOrder.createOrder(orderId, orderCategory,
									requestAccountId, requestPortfolioId);
							limitOrder.setLimit(priceLimit, timeStamp);
							limitOrder.setOrderCategory(orderCategory);
							limitOrder.setAccountId(requestAccountId);
							limitOrder.setPortfolioId(requestPortfolioId);
							limitOrder.display();
							limitOrder.initializeOrder();
							PortfolioRepository.getPortfolioRepository()
									.getAccount(requestAccountId).getOrders()
									.add(limitOrder);
						} else {
							MarketOrder marketOrder = new MarketOrder(order);
							marketOrder.setStockId(requestStockId);
							marketOrder.setQuantity(requestStockQuantity);
							marketOrder.setOrderCategory(orderCategory);
							marketOrder.setAccountId(requestAccountId);
							marketOrder.setPortfolioId(requestPortfolioId);

							orderId++;
							marketOrder.createOrder(orderId, orderCategory,
									requestAccountId, requestPortfolioId);
							marketOrder.display();
							marketOrder.initializeOrder();
							PortfolioRepository.getPortfolioRepository()
									.getAccount(requestAccountId).getOrders()
									.add(marketOrder);
						}
					} else {

						if ((OrderCategory.BUY).equals(orderCategory)) {
							MutualFund mutualFund = MutualFundRepository
									.getMutualFundRepository().getMutualFund(
											requestMutualFundId);
							double mutualFundPrice = mutualFund
									.getMutualFundPrice();
							boolean hasSufficientBalance = order
									.hasSufficientBalance(requestAccountId,
											mutualFundPrice, requestMFQuantity);
							if (!hasSufficientBalance) {
								System.out
										.println("Account does not have sufficient Balance!");
								break;
							}
						}
						order.setMutualFundId(requestMutualFundId);
						order.setQuantity(requestMFQuantity);
						orderId++;
						order.createOrder(orderId, orderCategory, accountId,
								portfolioId);
						order.setAccountId(requestAccountId);
						order.setPortfolioId(requestPortfolioId);
						order.display();
						order.initializeOrder();
						PortfolioRepository.getPortfolioRepository()
								.getAccount(requestAccountId).getOrders()
								.add(order);
					}

					OrderRepository orderRepository = OrderRepository
							.getOrderRepository();
					orderRepository.addOrder(order);
					break;
				}
				case 2: {
					ArrayList<AbstractOrder> orders = OrderRepository
							.getOrderRepository().getOrdersFromAccount(
									requestAccountId);
					for (AbstractOrder order : orders) {
						if (OrderType.LIMIT.equals(order.getOrderType())) {
							LimitOrder limitOrder = new LimitOrder(order);
							limitOrder.display();
						} else if (OrderType.MARKET
								.equals(order.getOrderType())) {
							MarketOrder marketOrder = new MarketOrder(order);
							marketOrder.display();
						} else {
							order.display();
						}
					}
					break;
				}
				case 3: {
					StockOrder order = (StockOrder) OrderRepository
							.getOrderRepository().getInitializedOrActiveOrder(
									requestOrderId);
					LimitOrder limitOrder = new LimitOrder(order);
					if (OrderType.LIMIT.equals(order.getOrderType())) {
						limitOrder.setPriceLimit(requestNewPriceLimit);
						limitOrder.setQuantity(requestNewQuantity);
						limitOrder.setOrderPrice(requestNewPriceLimit
								* requestNewQuantity);
						System.out.println("Order has been Updated! ");
						limitOrder.display();
						limitOrder.initializeOrder();
					}
					break;
				}

				case 4: {
					AbstractOrder order = OrderRepository.getOrderRepository()
							.getInitializedOrActiveOrder(requestOrderId);
					if (order != null) {
						order.closeOrder(false);
					}
					break;
				}
				}
			}
		}
		}
	}
}
